var express = require('express');
var path = require('path');
var fs = require('fs');
var Websocket = require('ws');
var https = require('https');
var privateKey  = fs.readFileSync('./ssl/214302744950699.key', 'utf8');
var certificate = fs.readFileSync('./ssl/214302744950699.pem', 'utf8');
var credentials = {key: privateKey, cert: certificate};

var app = express();
var httpsServer = https.createServer(credentials, app);
app.use(express.static(path.resolve(__dirname, 'dist')));

app.get('/', (req, res) => {
    res.sendFile(path.resolve(__dirname, 'dist/index.html'));
})

httpsServer.listen(10000, () => {
    console.log('https run in 10000 port...')
})

var ws = new Websocket.Server({server: httpsServer});

var caches = {};
/**
 * type对应的事件
 * 
 * login： 用户登陆
 * join: 用户加入，（有用户登陆成功后广播）
 * offer: 会议信令
 * stopOffer: 关闭会议指令
 * answer: 应答信令
 * candidate: 代理服务器信息
 * checkLogin: 检查登陆状态
 * error: 出错后相应
 */
var handle = {
    login(conn, data) {
        const user = data.fromUser;
        console.log('User ' + user + ' is login;');
        if (caches[user]) {
            console.log('用户名已存在')
            return send(conn, {
                type: 'login',
                success: false
            });
        }
        console.log('用户已链接')

        caches[user] = conn;
        broadcast({
            type: 'join',
            fromUser: user,
            users: Object.keys(caches)
        });
        send(conn, {
            type: 'login',
            success: true,
            loginer: user
        });
    },
    offer(conn, data) {
        const {remoteUser, offer, fromUser} = data;
        const remoteConn = caches[remoteUser];
        console.log(remoteUser)
        console.log(Object.keys(caches))
        if (!remoteConn) {
            return send(conn, {
                type: 'unline',
                message: '用户不在线'
            });
        }

        console.log('Send offer to ' + remoteUser)

        send(remoteConn, {
            type: 'offer',
            offer,
            fromUser
        });
    },
    stopOffer(conn, data) {
        const {remoteUser, fromUser} = data;
        const remoteConn = caches[remoteUser];
        if (remoteConn) {
            send(remoteConn, {
                type: 'stopOffer',
                fromUser
            });
        }
    },
    answer(conn, data) {
        const {remoteUser, answer, fromUser} = data;
        const remoteConn = caches[remoteUser];
        
        if (!remoteConn) {
            return send(conn, {
                type: 'unline',
                message: '用户不在线'
            });
        }

        console.log('Send answer to ' + remoteUser)

        send(remoteConn, {
            type: 'answer',
            answer,
            fromUser
        });
    },
    candidate(conn, data) {
        const {remoteUser, candidate} = data;
        const remoteConn = caches[remoteUser];
        if (!remoteConn) {
            return send(conn, {
                type: 'unline',
                message: '用户不在线'
            });
        }

        console.log('Send candidate to ' + remoteUser);

        send(remoteConn, {
            type: 'candidate',
            candidate
        });
    },
    checkLogin(conn, data) {
        const {remoteUser} = data;
        const remoteConn = caches[remoteUser];
        console.log('checkLogin for : ' + remoteUser)
        if (remoteConn) {
            return send(conn, {
                type: 'checkLogin',
                isLogin: true
            })
        } 
        send(conn, {
            type: 'checkLogin',
            isLogin: false
        });
    },
    error(conn, data) {
        send(conn, {
            type: 'error',
            message: 'message通信出错了'
        })
    }
}

ws.on('connection', (connection) => {
    console.log('connection.....')
    connection.on('message', (data) => {
        data = JSON.parse(data);
        const type = data.type;
        let func = handle[type];
        if (!func) {
            func = handle.error;
        }
        func(connection, data);
    });

    connection.on('error', (err) => {
        close(connection);
        console.log('err is : ', err);
    });

    connection.on('close', (data) => {
        console.log('connection is close');
        close(connection);
    });
});

function send(connection, data) {
    if (typeof data !== 'string') {
        data = JSON.stringify(data);
    }
    connection.send(data);
}
function close(currentConn) {
    let currentUser = getUserNameByConnection(currentConn);

    delete caches[currentUser];

    broadcast({
        type: 'leave',
        fromUser: currentUser
    });
}

function getUserNameByConnection (currentConn) {
    var currentUser = '';
    Object.keys(caches).some(userName => {
        const conn = caches[userName];
        if (conn === currentConn) {
            currentUser = userName;
            return true;
        }
    });
    return currentUser;
}

function broadcast(data) {
    for (var name in caches) {
        const conn = caches[name];
        send(conn, data);
    }
}
